package vek.ObjectDatabase;

import java.util.ArrayList;

/**
 * Contains search paramaters which are used to search for POIs by the databases.
 * Keeps a search history and can remove searches based on the type of search.
 * This class is based on the Command design pattern and when instantiated it is essentially search arguments put into an object.
 * @author Christian, Michal og Jakob (Hold 1, gruppe 2)
 */
public class Search {
    
    public enum SearchType {NAMESTARTSWITH, TYPESTARTSWITH, TYPEEQUALS, PHONENUMBERSTARTSWITH,
    ROADSTARTSWITH, ISOPEN, HASTOILETS, HASELEVATORS, ISHANDICAPFRIENDLY, ISWITHXMETERS } // the types of searches, this is used when a search type is removed
    
    private ArrayList<SearchType> searches; // the search type
    private ArrayList<String[]> searchArguments; // the search arguments. 
    //the first string array in the ArrayList should equal the search arguments for the first search type in the "searches" variable
    
    public Search()
    {
        searches = new ArrayList<SearchType>();
        searchArguments = new ArrayList<String[]>();
    }
    
    /**
     * Gets all the various types of searches in this search
     * @return an ArrayList containing the SearchTypes
     */
    
    public ArrayList<SearchType> getSearcTypes()
    {
        return searches;
    }
    
    /**
     * Gets all the search arguments.
     * @return an ArrayList containing a String array. Each string array is a series of arguments, though typically only 1 argument is used
     */
    
    public ArrayList<String[]> getSearchArguments()
    {
        return searchArguments;
    }
    
    /**
     * Adds a new search argument to this search.
     * see SimpleDatabase for a explenation on what happens when a search object is received by a database
     * 
     * @param type the type of search, for example "NAMESTARTSWITH"
     * @param arg the arguments for the search type. for example "a", there can be multiple arguments for one search type.
     */
            
    
    public void addSearch(SearchType type, String arg[])
    {
        searches.add(type);
        searchArguments.add(arg);
        //System.out.println("ADDED: " + this); // debug
        //System.out.println(toStringFancy()); // debug
    }
    
    /**
     * Removes the last search of a specific type.
     * 
     * NOTE: this only removes the latest search of that type.
     * 
     * @param type the type of search to be removed
     */
    
    public void removeLastSearchOfType(SearchType type)
    {
        int index = searches.lastIndexOf(type);
        if(index != -1)
        {
            searches.remove(index);
            searchArguments.remove(index);
            System.out.println("REMOVED: " + this);
        }
    }
    
    /**
     * Checks if this search object contains the specified search type
     * @param type the type of search which this object could contain
     * @return true if the object contains the search type specified
     */
    
    public boolean containsSearchType(SearchType type)
    {
        return searches.contains(type);
    }
    
    /**
     * gets this search as a String, this is mostly used for debugging purposes.
     * @return this ojbect as a String with all the search types and search arguments
     */
    
    public String toString()
    {
        String output = "Search:";
        
        assert searches.size() == searchArguments.size() : "searches and search args size do not match";
        
        
        for(int i = 0; i < searches.size(); i++)
        {
            output += " " + i + " : " + searches.get(i) + ">";
            
            for(int n = 0; n < searchArguments.get(i).length; n++)
            {
                output += " " + searchArguments.get(i)[n] + ",";
            }
        }
        
        return output;
    }
    
    /**
     * Gets the name for the search type which is to be diplayed in the GUI for the user
     * @param type the type of search
     * @return String containing the fancy name of the search type for the end user
     */
    
    public String getFancyNameForSearchType(SearchType type)
    {
        if(type.equals(SearchType.HASELEVATORS))
        {
            return "elevatorer: ";
        }
        else if(type.equals(SearchType.HASTOILETS))
        {
            return "toiletter: ";
        }
        else if(type.equals(SearchType.ISHANDICAPFRIENDLY))
        {
            return "handikapvenlig: ";
        }
        else if(type.equals(SearchType.ISOPEN))
        {
            return "er åben: ";
        }
        else if(type.equals(SearchType.ISWITHXMETERS))
        {
            return "indenfor: ";
        }
        else if(type.equals(SearchType.NAMESTARTSWITH))
        {
            return "navn starter med: ";
        }
        else if(type.equals(SearchType.PHONENUMBERSTARTSWITH))
        {
            return "telefonnummer starter med: ";
        }
        else if(type.equals(SearchType.ROADSTARTSWITH))
        {
            return "vejnanvn starter med: ";
        }
        else if(type.equals(SearchType.TYPEEQUALS))
        {
            return "type: ";
        }
        else if(type.equals(SearchType.TYPESTARTSWITH))
        {
            return "type starter med: ";
        }
        else
        {
            assert false : "Search";
            return "not set";
        }

    }
    
    /**
     * Gets the entire search as a String to display it to the end user
     * @return the search object as a string, formattet to fit display in the GUI
     */
    
    public String toStringFancy()
    {
        String output = "";
        ArrayList<SearchType> searchesEncountered = new ArrayList<Search.SearchType>();
        ArrayList<String[]> searchArgs = new ArrayList<String[]>();
        
        for(int i = 0; i < searches.size(); i++)
        {
            if(searchesEncountered.contains(searches.get(i)))
            {
                searchArgs.set(searchesEncountered.indexOf( searches.get(i) ), searchArguments.get(i));
            }
            else
            {
                searchesEncountered.add(searches.get(i));
                searchArgs.add(searchArguments.get(i));
            }
        }
        
        for(int i = 0; i < searchesEncountered.size(); i++)
        {
            output += getFancyNameForSearchType(searchesEncountered.get(i));
            
            if(searchArgs.get(i).length > 1)
            {
                output += searchArgs.get(i)[3] + " meter, ";
            }
            else
            {
                output += searchArgs.get(i)[0] + ", ";
            }
        }
        if(output.length() > 2)
        {
          output = output.substring(0, output.length() - 2);  
        }
        return output;
    }

}
